1 package org.naftulin.classpathexplorer.dublicate.imlp;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.HashMap;
6 import java.util.Iterator;
7 import java.util.LinkedList;
8 import java.util.List;
9 import java.util.Map;
10
11 import org.naftulin.classpathexplorer.AccessibleResource;
12 import org.naftulin.logwrapper.LogAdapter;
13 import org.naftulin.logwrapper.LogLevelAdaptor;
14 import org.naftulin.timespan.TimeSpan;
15
16
17
18 /***
19 * Resource registry, singleton.
20 *
21 * @author henry naftulin
22 * @version 1.0
23 */
24 class ResourceRegistry {
25 private static final LogAdapter log = LogAdapter.getLogger(ResourceRegistry.class);
26 private static final AccessibleResource[] EMPTY_ARRAY = new AccessibleResource[0];
27
28 private static ResourceRegistry registry;
29 private Map resources = new HashMap(2000);
30 private List dublicatedResourceKeyList = new LinkedList();
31 private String[] path;
32
33 private ResourceRegistry() {}
34 /***
35 * Returns resource registry, which is created if needed.
36 * Based on GOF singleton pattern.
37 * @return resource registry, which is created if needed.
38 */
39 static synchronized ResourceRegistry getInstance() {
40 if (registry == null) {
41 registry = new ResourceRegistry();
42 }
43 return registry;
44 }
45
46 /***
47 * Returns resources based on the path sepcified.
48 * @param path
49 * @return resources based on the path sepcified.
50 */
51 synchronized AccessibleResource[] getResourcesByFullName(String path) {
52 AccessibleResource[] retArray = EMPTY_ARRAY;
53 AccessibleResource temp = (AccessibleResource) resources.get(path);
54 if (temp != null) {
55 if (temp instanceof AccessibleResourceListDecorator) {
56 List resourceList = new LinkedList();
57 AccessibleResourceListDecorator dec = (AccessibleResourceListDecorator) temp;
58 resourceList.add(temp);
59 while(temp instanceof AccessibleResourceListDecorator) {
60 dec = (AccessibleResourceListDecorator) temp;
61 temp = dec.getNextResource();
62 resourceList.add(temp);
63 }
64 retArray = new AccessibleResource[resourceList.size()];
65 retArray = (AccessibleResource[]) resourceList.toArray(retArray);
66 } else {
67 retArray = new AccessibleResource[1];
68 retArray[0] = temp;
69 }
70 }
71 return retArray;
72 }
73
74 /***
75 * Returns all resources with the specified name.
76 * @param name
77 * @return all resources with the specified name.
78 */
79 synchronized AccessibleResource[] getResroucesByName(String name) {
80 TimeSpan span = new TimeSpan("ResourceRegistry.getResourcesByName()");
81 span.start();
82 List resourceList = new LinkedList(resources.values());
83 List found = new LinkedList();
84 Iterator it = resourceList.iterator();
85 AccessibleResource temp;
86 while(it.hasNext()) {
87 temp = (AccessibleResource) it.next();
88 if (temp.getName().equals(name)) {
89 found.add(temp);
90 if (temp instanceof AccessibleResourceListDecorator) {
91 AccessibleResourceListDecorator dups= (AccessibleResourceListDecorator) temp;
92
93 while(temp instanceof AccessibleResourceListDecorator) {
94 dups =(AccessibleResourceListDecorator) temp;
95 temp = dups.getNextResource();
96 found.add(temp);
97 }
98 }
99 }
100
101 }
102 AccessibleResource[] arr = new AccessibleResource[found.size()];
103 arr = (AccessibleResource[]) found.toArray(arr);
104 span.stop();
105 span.log(log, LogLevelAdaptor.INFO);
106 return arr;
107 }
108
109 /***
110 * Returns all resources from the registry.
111 * @return all resources from the registry.
112 */
113 synchronized AccessibleResource[] getResrouces() {
114 TimeSpan span = new TimeSpan("ResourceRegistry.getResources()");
115 span.start();
116 List resourceList = new LinkedList(resources.values());
117 List duplicates = new LinkedList();
118 Iterator it = resourceList.iterator();
119 AccessibleResource temp;
120 while(it.hasNext()) {
121 temp = (AccessibleResource) it.next();
122 if (temp instanceof AccessibleResourceListDecorator) {
123 AccessibleResourceListDecorator dups= (AccessibleResourceListDecorator) temp;
124
125 while(temp instanceof AccessibleResourceListDecorator && dups.getNextResource()!= null) {
126 dups =(AccessibleResourceListDecorator) temp;
127 temp = dups.getNextResource();
128 duplicates.add(temp);
129 }
130 }
131 }
132 resourceList.addAll(duplicates);
133 AccessibleResource[] arr = new AccessibleResource[resourceList.size()];
134 arr = (AccessibleResource[]) resourceList.toArray(arr);
135 span.stop();
136 span.log(log, LogLevelAdaptor.INFO);
137 return arr;
138 }
139
140 /***
141 * Returns all the resources accessible from the archive.
142 * @param archive not null.
143 * @return all the resources accessible from the archive.
144 * @throws IOException if error occurs while reading resource.
145 * @exception IllegalArgumentException if archive is null
146 */
147 synchronized AccessibleResource[] getResrouces(AccessibleArchive archive) throws IOException {
148 if (archive == null) {
149 throw new IllegalArgumentException("archive cannot be null");
150 }
151 return archive.getAccessibleResources();
152 }
153
154 /***
155 * Returns dublicated resources.
156 * @return dublicated resources.
157 */
158 synchronized AccessibleResource[] getDublicatedResources() {
159 Iterator it = dublicatedResourceKeyList.iterator();
160 List resourceList = new LinkedList();
161 AccessibleResource resource;
162 while(it.hasNext()) {
163 resource = (AccessibleResource) resources.get(it.next());
164 while (resource instanceof AccessibleResourceListDecorator) {
165 resourceList.add(resource);
166 resource = ((AccessibleResourceListDecorator) resource).getNextResource();
167 }
168 if (resource != null) {
169 resourceList.add(resource);
170 }
171 }
172 AccessibleResource[] arr = new AccessibleResource[resourceList.size()];
173 arr = (AccessibleResource[]) resourceList.toArray(arr);
174 return arr;
175 }
176
177 /***
178 * Returns true if a resource is dublicated.
179 * @param resource not null.
180 * @return true if a resource is dublicated.
181 * @exception IllegalArgumentException if resource is null
182 */
183 synchronized boolean isResourceDublicated(AccessibleResource resource) {
184 if (resource == null) {
185 throw new IllegalArgumentException("resource cannot be null");
186 }
187 String key = resource.getKey();
188 return dublicatedResourceKeyList.contains(key);
189 }
190
191 /***
192 * Returns true if any resource is dublicated in the resource registry.
193 * @return true if any resource is dublicated in the resource registry.
194 */
195 synchronized boolean isAnyResourceDublicated() {
196 return dublicatedResourceKeyList.size() > 0;
197 }
198
199 /***
200 * Returns the number resource dublicate resources.
201 * @return the number resource dublicate resources.
202 */
203 synchronized int numResourceDublicated() {
204 return dublicatedResourceKeyList.size();
205 }
206
207 /***
208 * Clears the registry.
209 */
210 synchronized void clearRegistry() {
211 resources.clear();
212 dublicatedResourceKeyList.clear();
213 }
214
215 /***
216 * Returns the size of regustry. All resources are counted, dublicated or not.
217 * @return the size of regustry.
218 */
219 synchronized int registrySize() { return resources.size(); }
220
221 /***
222 * Adds a resource to the resource registry. The resource is added
223 * based on it's {@link AccessibleResource#getKey() key}.
224 * @param resource to be added to the registry, not null.
225 * @exception IllegalArgumentException if resource is null
226 */
227 synchronized void addResource(AccessibleResource resource) {
228 if (resource == null) {
229 throw new IllegalArgumentException("resource cannot be null");
230 }
231 String key = resource.getKey();
232 if (resources.containsKey(key)) {
233 AccessibleResource next = (AccessibleResource) resources.get(key);
234 resources.put(key, new AccessibleResourceListDecorator(resource, next));
235 if (!dublicatedResourceKeyList.contains(key)) {
236 dublicatedResourceKeyList.add(key);
237 }
238 } else {
239 resources.put(key, resource);
240 }
241 }
242
243 /***
244 * Given path (path from class path) creates accessible archive resources for
245 * all the path that were not scanned already. If the path was scanned already,
246 * for example class path contains an entry twice, the path is not rescanned.
247 * Null entries are returned for the dublicate archives
248 * @param accessiblePath path from class path - either directories or archives.
249 * @return an array of accessible archives, with either archives or null entries.
250 */
251 private AccessibleArchive[] getAccessibleArcives(String[] accessiblePath) {
252 AccessibleArchive[] archives = new AccessibleArchive[accessiblePath.length];
253 for (int i=0; i < archives.length; ++i) {
254 archives[i] = ArchiveFactory.createArchive(new File(accessiblePath[i]));
255 if (!resources.containsKey(archives[i].getKey())) {
256 log.log(LogLevelAdaptor.DEBUG,"added accessible arcive: " + archives[i]);
257 addResource(archives[i]);
258 } else {
259
260 archives[i]=null;
261 }
262 }
263 return archives;
264 }
265
266 /***
267 * Discovers resources. Archive is scanned only once, even if path contains entries pointing to the same
268 * archive. To re-scan the archive we first need to clear the registry.
269 * @param paths
270 */
271 protected synchronized void discoverResources(String[] paths) {
272 this.path = paths;
273 TimeSpan timeSpan = new TimeSpan("ResourceRegistry.discoverResources()");
274 timeSpan.start();
275 AccessibleArchive[] archives = getAccessibleArcives(paths);
276 for(int i=0; i < archives.length; ++i) {
277 if (archives[i]!= null) {
278 try {
279 AccessibleResource[] resources = archives[i].getAccessibleResources();
280 if (resources != null) {
281 for(int j=0; j < resources.length; ++j) {
282 addResource(resources[j]);
283 }
284 }
285 } catch(IOException e) {
286 log.log(LogLevelAdaptor.WARN, "Cannot get resources for archive: " + archives[i] + ". Skipping the archive.", e);
287 }
288 }
289 }
290 timeSpan.stop();
291 timeSpan.log(log, LogLevelAdaptor.DEBUG);
292 }
293
294 /***
295 * Returns the paths that were considered for discovering resources
296 * @return the paths that were considered for discovering resources
297 */
298 public String[] getPath() { return path; }
299 }